/**
 * @file boards\gd32f103cb\bsp\bsp_ioi2c.c
 *
 * Copyright (C) 2023
 *
 * bsp_ioi2c.c is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author HinsShum hinsshum@qq.com
 *
 * @encoding utf-8
 */

/*---------- includes ----------*/
#include "i2c_bus.h"
#include "gd32f10x_libopt.h"
#include "options.h"

/*---------- macro ----------*/
/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
static bool bsp_init(void);
static void bsp_deinit(void);
static void bsp_scl_set(bool on);
static bool bsp_scl_get(void);
static void bsp_sda_set(bool on);
static bool bsp_sda_get(void);
static void bsp_delay(void);

/*---------- variable ----------*/
static i2c_bus_describe_t ioi2c0 = {
    .data = NULL,
    .ops.init = bsp_init,
    .ops.deinit = bsp_deinit,
    .ops.scl_set = bsp_scl_set,
    .ops.scl_get = bsp_scl_get,
    .ops.sda_set = bsp_sda_set,
    .ops.sda_get = bsp_sda_get,
    .ops.delay = bsp_delay,
    .ops.lock = NULL,
    .ops.unlock = NULL
};
DEVICE_DEFINED(ioi2c0, i2c_bus, &ioi2c0);

/*---------- function ----------*/
static bool bsp_init(void)
{
    /* I2C GPIO:
     *  SCL: GPIOB10
     *  SDA: GPIOB11
     */
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_11 | GPIO_PIN_10);
    gpio_bit_set(GPIOB, GPIO_PIN_11 | GPIO_PIN_10);
    gpio_bit_reset(GPIOB, GPIO_PIN_3);

    return true;
}

static void bsp_deinit(void)
{
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_11 | GPIO_PIN_10);
    gpio_bit_set(GPIOB,GPIO_PIN_3 | GPIO_PIN_11 | GPIO_PIN_10);
}

static void bsp_scl_set(bool on)
{
    if (on) {
        gpio_bit_set(GPIOB, GPIO_PIN_10);
    }
    else {
        gpio_bit_reset(GPIOB, GPIO_PIN_10);
    }
}

static bool bsp_scl_get(void)
{
    return (SET == gpio_input_bit_get(GPIOB, GPIO_PIN_10));
}

static void bsp_sda_set(bool on)
{
    if (on) {
        gpio_bit_set(GPIOB, GPIO_PIN_11);
    }
    else {
        gpio_bit_reset(GPIOB, GPIO_PIN_11);
    }
}

static bool bsp_sda_get(void)
{
    return (SET == gpio_input_bit_get(GPIOB, GPIO_PIN_11));
}

static void bsp_delay(void)
{
    __delay_us(5);
}
